import os
import threading
import struct
from src.utils.error import FileExistsException, FileNotExistsException, FileCannotRWException, BadXIDFileException
from src.utils.parser import Parser

class TransactionManager:
    # 事务状态常量
    ACTIVE = 0
    COMMITTED = 1
    ABORTED = 2
    
    # XID文件头长度
    LEN_XID_HEADER_LENGTH = 8
    # 每个事务的占用长度
    XID_FIELD_SIZE = 1
    # 超级事务，永远为committed状态
    SUPER_XID = 0
    # XID文件后缀
    XID_SUFFIX = ".xid"

    def __init__(self, path):
        self.path = path
        self.xid_file = None  # 持久化文件
        self.xid_counter = 0
        self.counter_lock = threading.RLock()
        self.file = None
        self.fc = None  # 在Python中我们直接使用file对象

    @staticmethod
    def create(path):
        """创建一个新的事务管理器"""
        # 创建XID文件
        xid_path = path + TransactionManager.XID_SUFFIX
        try:
            if os.path.exists(xid_path):
                raise FileExistsException()
            # 创建文件
            with open(xid_path, 'wb') as f:
                # 写入空的XID文件头
                f.write(bytes(TransactionManager.LEN_XID_HEADER_LENGTH))
        except FileExistsException:
            raise FileExistsException()
        except Exception as e:
            raise e

        # 检查文件权限
        if not os.access(xid_path, os.R_OK | os.W_OK):
            raise FileCannotRWException()

        # 打开文件
        file = open(xid_path, 'r+b')
        
        # 创建事务管理器实例
        tm = TransactionManager(path)
        tm.file = file
        tm.fc = file  # 在Python中我们直接使用file对象
        
        return tm

    @staticmethod
    def open(path):
        """打开一个已存在的事务管理器"""
        # 检查XID文件是否存在
        xid_path = path + TransactionManager.XID_SUFFIX
        if not os.path.exists(xid_path):
            raise FileNotExistsException()
        
        # 检查文件权限
        if not os.access(xid_path, os.R_OK | os.W_OK):
            raise FileCannotRWException()

        # 打开文件
        try:
            file = open(xid_path, 'r+b')
        except Exception as e:
            raise e

        # 创建事务管理器实例
        tm = TransactionManager(path)
        tm.file = file
        tm.fc = file  # 在Python中我们直接使用file对象
        tm.check_xid_counter()  # 检查XID文件
        
        return tm

    def check_xid_counter(self):
        """检查XID文件是否合法"""
        try:
            # 获取文件长度
            self.file.seek(0, 2)  # 移动到文件末尾
            file_len = self.file.tell()  # 获取文件长度
            
            # 检查文件长度是否小于头部长度
            if file_len < self.LEN_XID_HEADER_LENGTH:
                raise BadXIDFileException()
            
            # 读取XID计数器
            self.file.seek(0)  # 移动到文件开头
            counter_bytes = self.file.read(self.LEN_XID_HEADER_LENGTH)
            self.xid_counter = Parser.parse_long(counter_bytes)
            
            # 计算理论文件长度并比较
            expected_len = self.get_xid_position(self.xid_counter + 1)
            if expected_len != file_len:
                raise BadXIDFileException()
                
        except Exception as e:
            if isinstance(e, BadXIDFileException):
                raise e
            else:
                raise BadXIDFileException() from e

    def get_xid_position(self, xid):
        """根据事务xid取得其在xid文件中对应的位置"""
        return self.LEN_XID_HEADER_LENGTH + (xid - 1) * self.XID_FIELD_SIZE

    def update_xid(self, xid, status):
        """更新xid事务的状态为status"""
        offset = self.get_xid_position(xid)
        status_byte = bytes([status])  # 将状态转换为字节
        
        try:
            # 写入状态
            self.file.seek(offset)
            self.file.write(status_byte)
            # 强制刷新到磁盘
            self.file.flush()
            os.fsync(self.file.fileno())
        except Exception as e:
            raise e

    def incr_xid_counter(self):
        """将XID加一，并更新XID Header"""
        self.xid_counter += 1
        counter_bytes = Parser.long_to_bytes(self.xid_counter)
        
        try:
            # 写入计数器
            self.file.seek(0)
            self.file.write(counter_bytes)
            # 强制刷新到磁盘
            self.file.flush()
            os.fsync(self.file.fileno())
        except Exception as e:
            raise e

    def begin(self):
        """开始事务，返回事务ID"""
        with self.counter_lock:
            xid = self.xid_counter + 1
            self.update_xid(xid, self.ACTIVE)
            self.incr_xid_counter()
            return xid

    def commit(self, xid):
        """提交事务"""
        self.update_xid(xid, self.COMMITTED)

    def abort(self, xid):
        """中止事务"""
        self.update_xid(xid, self.ABORTED)

    def check_xid(self, xid, status):
        """检测XID事务是否处于status状态"""
        offset = self.get_xid_position(xid)
        try:
            # 读取状态
            self.file.seek(offset)
            status_byte = self.file.read(self.XID_FIELD_SIZE)
            return status_byte[0] == status
        except Exception as e:
            raise e

    def is_active(self, xid):
        """检查事务是否处于活跃状态"""
        if xid == self.SUPER_XID:
            return False
        return self.check_xid(xid, self.ACTIVE)

    def is_committed(self, xid):
        """检查事务是否已提交"""
        if xid == self.SUPER_XID:
            return True
        return self.check_xid(xid, self.COMMITTED)

    def is_aborted(self, xid):
        """检查事务是否已中止"""
        if xid == self.SUPER_XID:
            return False
        return self.check_xid(xid, self.ABORTED)

    def close(self):
        """关闭事务管理器"""
        try:
            if self.file:
                self.file.close()
        except Exception as e:
            raise e